﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Casamiel.Common
{
	public static class DistanceHelper
	{
		/// <summary>
		/// 根据一个给定经纬度的点和距离，进行附近地点查询
		/// </summary>
		/// <param name="longitude">经度</param>
		/// <param name="latitude">纬度</param>
		/// <param name="distance">距离（单位：公里或千米）</param>
		/// <returns>返回一个范围的4个点，最小纬度和纬度，最大经度和纬度</returns>
		public static PositionModel FindNeighPosition(double longitude, double latitude, double distance)
		{
			//先计算查询点的经纬度范围  
			double r = 6378.137;//地球半径千米  
			double dis = distance;//千米距离    
            double dlng = 2 * Math.Asin(Math.Sin(dis / (2 * r)) / Math.Cos(latitude * Math.PI / 180));
            if (Math.Sin(dis / (2 * r)) / Math.Cos(latitude * Math.PI / 180) > 1)
            {
                dlng = 0;
            }
            if (Math.Sin(dis / (2 * r)) / Math.Cos(latitude * Math.PI / 180) <-1)
            {
                dlng = 0;
            }
            dlng = dlng * 180 / Math.PI;//角度转为弧度  
			double dlat = dis / r;
			dlat = dlat * 180 / Math.PI;
			double minlat = latitude - dlat;
			double maxlat = latitude + dlat;
			double minlng = longitude - dlng;
			double maxlng = longitude + dlng;
			return new PositionModel
			{
				MinLat = minlat,
				MaxLat = maxlat,
				MinLng = minlng,
				MaxLng = maxlng
			};
		}
         
		/// <summary>
		/// 计算两点位置的距离，返回两点的距离，单位：公里或千米
		/// 该公式为GOOGLE提供，误差小于0.2米
		/// </summary>
		/// <param name="lat1">第一点纬度</param>
		/// <param name="lng1">第一点经度</param>
		/// <param name="lat2">第二点纬度</param>
		/// <param name="lng2">第二点经度</param>
		/// <returns>返回两点的距离，单位：公里或千米</returns>
		public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
		{
			//地球半径，单位米
			double EARTH_RADIUS = 6378137;
			double radLat1 = Rad(lat1);
			double radLng1 = Rad(lng1);
			double radLat2 = Rad(lat2);
			double radLng2 = Rad(lng2);
			double a = radLat1 - radLat2;
			double b = radLng1 - radLng2;
			double result = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))) * EARTH_RADIUS;
			return result / 1000;
		}

		/// <summary>
		/// 经纬度转化成弧度
		/// </summary>
		/// <param name="d"></param>
		/// <returns></returns>
		private static double Rad(double d)
		{
			return (double)d * Math.PI / 180d;
		}
	}
}
